#include "Generate_C_std.h"

#include "Pattern_assign_value.h"

// Isset uses Pattern_assign_value, as it only has a boolean value. It puts the
// BOOL into the ready made zval.
class Pattern_assign_expr_isset : public Pattern_assign_value
{
	Expr* rhs_pattern()
	{
		isset = new Wildcard<Isset>;
		return isset;
	}

	void initialize(string lhs)
	{
		VARIABLE_NAME* var_name = dynamic_cast<VARIABLE_NAME*> (isset->value->variable_name);

		if (var_name)
		{
			if (isset->value->array_indices->size() == 0)
			{
				if (var_name->attrs->is_true ("phc.codegen.st_entry_not_required"))
				{
					string name = get_non_st_name (var_name);
					buf 
					<< "ZVAL_BOOL(" << lhs << ", " 
					<< name << " != NULL && !ZVAL_IS_NULL(" << name << "));\n"; 
				}
				else
				{
					buf
					<< read_rvalue ("rhs", var_name)
					<< "ZVAL_BOOL(" << lhs << ", !ZVAL_IS_NULL (rhs));\n" 
					;
				}
			}
			else 
			{
				// TODO this can have > 1 array_index
				assert(isset->value->array_indices->size() == 1);
				Rvalue* index = isset->value->array_indices->front();

				buf
				<< get_st_entry (LOCAL, "u_array", var_name)
				<< read_rvalue ("u_index", index)
				<< "ZVAL_BOOL(" << lhs << ", "
				<< "isset_array ("
				<<    "u_array, "
				<<    "u_index));\n"
				;
			}
		}
		else
		{
			// Variable variable
			// TODO
			assert(isset->value->array_indices->size() == 0);
			Variable_variable* var_var = dyc<Variable_variable> (isset->value->variable_name);

			buf
			<< "zvalT rhs;\n"
			<< read_rvalue ("index", var_var->variable_name)
			<< read_var_var ("rhs", "index")
			<< "ZVAL_BOOL(" << lhs << ", !ZVAL_IS_NULL(rhs));\n" 
			;
		}
	}

protected:
	Wildcard<Isset>* isset;
};


CREATE(Pattern_assign_expr_isset);
